package top.suven.base.http.admin.user.service.impl;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import top.suven.base.core.mybatis.PageData;
import top.suven.base.core.redis.RedisClusterServer;
import top.suven.base.core.redis.RedisConstants;
import top.suven.base.core.redis.RedisKeys;
import top.suven.base.http.admin.user.dao.UserWebDao;
import top.suven.base.http.admin.user.model.User;
import top.suven.base.http.admin.user.model.UserRegisterInfo;
import top.suven.base.http.admin.user.service.UserWebService;
import top.suven.base.http.admin.user.vo.response.UserRegisterStatisticsVo;
import top.suven.base.http.admin.user.vo.response.UserResponseVo;
import top.suven.base.http.admin.user.vo.response.UserWeekRegisterVo;
import top.suven.base.http.enums.EnableStatusEnum;
import top.suven.base.http.enums.PlatformEnumType;
import top.suven.base.util.utilize.BeanUtil;
import top.suven.base.util.utilize.JsonUtils;

import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Title: UserWebServiceImpl.java
 * @Description: 用户的业务处理服务类
 * @author lixiangling
 * @date   2018/08/28 16:10:56
 * @version V1.0.0
 * ----------------------------------------------------------------------------
 *  modifyer    modifyTime                 comment
 *
 * ----------------------------------------------------------------------------
 *
 */
@Component("userWebService")
public class UserWebServiceImpl implements UserWebService {
    private final static Logger logger = LoggerFactory.getLogger(UserWebServiceImpl.class);
    @Autowired
    private RedisClusterServer redisClusterServer;
    @Autowired
    private UserWebDao  userWebDao;

    private static final String CLIENT_TYPE_OTHER = "other";
    /**
     * @Title: 获取用户分页信息
     * @Description:
     * @param user @{Link User}
     * @return
     * @throw
     * @author lixiangling
     * @date 2018/08/28 16:10:56
     *  --------------------------------------------------------
     *  modifyer    modifyTime                 comment
     *
     *  --------------------------------------------------------
     */
    public PageData<UserResponseVo> getUserPage(User user, int start, int pageSize){
        int count = userWebDao.countEntity(user);
        if(count == 0){
            return new PageData<UserResponseVo>(Collections.EMPTY_LIST,count);
        }
        List<User> userList = userWebDao.findPageEntity(user, start, pageSize);
        if(userList == null || userList.isEmpty()){
            return new PageData<UserResponseVo>(Collections.EMPTY_LIST,count);
        }
        List<UserResponseVo> userResponseList = userList.stream().map(userResponse -> {
            UserResponseVo userResponseVo = new UserResponseVo();
            BeanUtil.copyProperties(userResponse, userResponseVo);
            return userResponseVo;
        }).collect(Collectors.toList());
        return new PageData<UserResponseVo>(userResponseList,count);
    }
    /**
     * @Title: 获取用户列表信息
     * @Description:
     * @param user @{Link User}
     * @return
     * @throw
     * @author lixiangling
     * @date 2018/08/28 16:10:56
     *  --------------------------------------------------------
     *  modifyer    modifyTime                 comment
     *
     *  --------------------------------------------------------
     */
    public List<User> getUserList(User user){
        return userWebDao.findEntity(user);
    }

    /**
     * @Title: 新增用户信息
     * @Description:
     * @param user @{Link User}
     * @return
     * @throw
     * @author lixiangling
     * @date 2018/08/28 16:10:56
     *  --------------------------------------------------------
     *  modifyer    modifyTime                 comment
     *
     *  --------------------------------------------------------
     */
    public void addUser(User user){
        userWebDao.createEntity(user);
    }
    /**
    * @Title: 修改用户信息
    * @Description:
    * @param user @{Link User}
    * @return
    * @throw
    * @author lixiangling
    * @date 2018/08/28 16:10:56
    *  --------------------------------------------------------
    *  modifyer    modifyTime                 comment
    *
    *  --------------------------------------------------------
    */
    public void updUser(User user){
        userWebDao.updateEntity(user);
    }
   /**
    * @Title: 获取用户信息
    * @Description:
    * @param id @{Link Long}
    * @return
    * @throw
    * @author lixiangling
    * @date 2018/08/28 16:10:56
    *  --------------------------------------------------------
    *  modifyer    modifyTime                 comment
    *
    *  --------------------------------------------------------
    */
    public User getUser(Long id){
        User user = new User();
        user.setUserId(id);
        return userWebDao.retrieveEntity(user);
    }
    /**
     * @Title: 删除用户信息
     * @Description:
     * @param ids @{Link Long[]}
     * @return
     * @throw
     * @author lixiangling
     * @date 2018/08/28 16:10:56
     *  --------------------------------------------------------
     *  modifyer    modifyTime                 comment
     *
     *  --------------------------------------------------------
     */
    public void del(Long[] ids){
        userWebDao.del(Arrays.asList(ids));
    }
   /**
    * @Title: 启用用户信息
    * @Description:
    * @param ids @{Link Long[]}
    * @return
    * @throw
    * @author lixiangling
    * @date 2018/08/28 16:10:56
    *  --------------------------------------------------------
    *  modifyer    modifyTime                 comment
    *
    *  --------------------------------------------------------
    */
    public void turnOn(Long[] ids){
        userWebDao.updateEnableStatus(EnableStatusEnum.ENABLE.getIndexStr(), Arrays.asList(ids));
    }
   /**
    * @Title: 禁用用户信息
    * @Description:
    * @param ids @{Link Long[]}
    * @return
    * @throw
    * @author lixiangling
    * @date 2018/08/28 16:10:56
    *  --------------------------------------------------------
    *  modifyer    modifyTime                 comment
    *
    *  --------------------------------------------------------
    */
    public void turnOff(Long[] ids){
        userWebDao.updateEnableStatus(EnableStatusEnum.DISABLE.getIndexStr(), Arrays.asList(ids));
    }
    /**
     * @Title: 获取一周的注册信息
     * @Description:
     * @param
     * @return
     * @throw
     * @author lixiangling
     * @date 2018/8/28 16:33
     *  --------------------------------------------------------
     *  modifyer    modifyTime                 comment
     *
     *  --------------------------------------------------------
     */
    @Override
    public UserWeekRegisterVo getWeekRegisterCount() {
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        UserWeekRegisterVo userWeekRegisterVo = new UserWeekRegisterVo();
        String registerInfo = redisClusterServer.get(String.format("%s%s",RedisKeys.USER_WEEK_REGISTER_INFO,format.format(new Date())));
        if(StringUtils.isNotBlank(registerInfo)){
            return JsonUtils.readValue(registerInfo, UserWeekRegisterVo.class);
        }
        List<UserRegisterInfo> userRegisterInfoList = userWebDao.getWeekRegisterCount();
        if(userRegisterInfoList == null || userRegisterInfoList.isEmpty()){
            return userWeekRegisterVo;
        }
        String[] registerTimes = new String[7];
        Calendar calendar = Calendar.getInstance();
        for (int i = 6 ; i>=0; i--){
            calendar.add(Calendar.DATE,-1);
            registerTimes[i] = format.format(calendar.getTime());
        }

        userWeekRegisterVo.setRegisterTimes(registerTimes);
        userWeekRegisterVo.setAndroidCounts(new long[registerTimes.length]);
        userWeekRegisterVo.setIosCounts(new long[registerTimes.length]);
        userWeekRegisterVo.setPcCounts(new long[registerTimes.length]);
        userWeekRegisterVo.setOtherCounts(new long[registerTimes.length]);

        for(UserRegisterInfo userRegisterInfo : userRegisterInfoList){
            for(int i=0,length=registerTimes.length;i<length;i++){
                if(!userRegisterInfo.getRegisterTime().equals(registerTimes[i])){
                    continue;
                }
                if(StringUtils.isBlank(userRegisterInfo.getClient())){
                    userWeekRegisterVo.getOtherCounts()[i] += userRegisterInfo.getCount();
                }else if(userRegisterInfo.getClient().startsWith(PlatformEnumType.ANDROID.getKey())){
                    userWeekRegisterVo.getAndroidCounts()[i] += userRegisterInfo.getCount();
                }else if(userRegisterInfo.getClient().startsWith(PlatformEnumType.IOS.getKey())){
                    userWeekRegisterVo.getIosCounts()[i] += userRegisterInfo.getCount();
                }else if(userRegisterInfo.getClient().startsWith(PlatformEnumType.PC.getKey())||userRegisterInfo.getClient().startsWith("pc")){
                    userWeekRegisterVo.getPcCounts()[i] += userRegisterInfo.getCount();
                }else{
                    userWeekRegisterVo.getOtherCounts()[i] += userRegisterInfo.getCount();
                }
            }
        }
        redisClusterServer.setex(String.format("%s%s",RedisKeys.USER_WEEK_REGISTER_INFO,format.format(new Date())),JsonUtils.toJsonString(userWeekRegisterVo), RedisConstants.ONE_DAY);
        return userWeekRegisterVo;
    }
    /**
     * @Title: 获取注册统计信息（同比，环比）
     * @Description:
     * @param
     * @return
     * @throw
     * @author lixiangling
     * @date 2018/8/30 17:49
     *  --------------------------------------------------------
     *  modifyer    modifyTime                 comment
     *
     *  --------------------------------------------------------
     */
    public UserRegisterStatisticsVo getRegisterStatistics(){
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        String now = format.format(new Date());
        UserRegisterStatisticsVo userRegisterStatisticsVo = new UserRegisterStatisticsVo();
        String registerInfo = redisClusterServer.get(String.format("%s%s",RedisKeys.USER_REGISTER_STATISTIC_INFO, now));
        if(StringUtils.isNotBlank(registerInfo)){
            return JsonUtils.readValue(registerInfo, UserRegisterStatisticsVo.class);
        }
        List<UserRegisterInfo> userRegisterInfoList = userWebDao.getWeekRegisterCount();
        if(userRegisterInfoList == null || userRegisterInfoList.isEmpty()){
            return userRegisterStatisticsVo;
        }

        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.DATE,-1);
        String yesterday = format.format(calendar.getTime());
        calendar.add(Calendar.MONTH,-1);
        String lastMonthYesterDay = format.format(calendar.getTime());
        calendar.add(Calendar.MONTH,1);
        calendar.add(Calendar.YEAR,-1);
        String lastYearYesterDay = format.format(calendar.getTime());
        for(UserRegisterInfo userRegisterInfo : userRegisterInfoList) {
            setClientStatistics(userRegisterStatisticsVo,userRegisterInfo,yesterday,"",lastMonthYesterDay,lastYearYesterDay);
        }

        userRegisterStatisticsVo.setRegisterTime(yesterday);
        DecimalFormat numberFormat = new DecimalFormat("##.##");

        //安卓环比
        userRegisterStatisticsVo.setAndroidRingRatio(Float.parseFloat(numberFormat.format((userRegisterStatisticsVo.getAndroidCount()-userRegisterStatisticsVo.getAndroidPreMonthCount())/
                (userRegisterStatisticsVo.getAndroidPreMonthCount()==0?1f:userRegisterStatisticsVo.getAndroidPreMonthCount()))));
        //安卓同比
        userRegisterStatisticsVo.setAndroidYearOnYear(Float.parseFloat(numberFormat.format( (userRegisterStatisticsVo.getAndroidCount()-userRegisterStatisticsVo.getAndroidPreYearCount())/
                (userRegisterStatisticsVo.getAndroidPreYearCount()==0?1f:userRegisterStatisticsVo.getAndroidPreYearCount()))));

        //IOS环比
        userRegisterStatisticsVo.setIosRingRatio(Float.parseFloat(numberFormat.format((userRegisterStatisticsVo.getIosCount()-userRegisterStatisticsVo.getIosPreMonthCount())/
                (userRegisterStatisticsVo.getIosPreMonthCount()==0?1f:userRegisterStatisticsVo.getIosPreMonthCount()))));
        //IOS同比
        userRegisterStatisticsVo.setIosYearOnYear(Float.parseFloat(numberFormat.format( (userRegisterStatisticsVo.getIosCount()-userRegisterStatisticsVo.getIosPreYearCount())/
                (userRegisterStatisticsVo.getIosPreYearCount()==0?1f:userRegisterStatisticsVo.getIosPreYearCount()))));

        //PC环比
        userRegisterStatisticsVo.setPcRingRatio(Float.parseFloat(numberFormat.format( (userRegisterStatisticsVo.getPcCount()-userRegisterStatisticsVo.getPcPreMonthCount())/
                (userRegisterStatisticsVo.getPcPreMonthCount()==0?1f:userRegisterStatisticsVo.getPcPreMonthCount()))));
        //PC同比
        userRegisterStatisticsVo.setPcYearOnYear(Float.parseFloat(numberFormat.format( (userRegisterStatisticsVo.getPcCount()-userRegisterStatisticsVo.getPcPreYearCount())/
                (userRegisterStatisticsVo.getPcPreYearCount()==0?1f:userRegisterStatisticsVo.getPcPreYearCount()))));

        //其他环比
        userRegisterStatisticsVo.setOtherRingRatio(Float.parseFloat(numberFormat.format( (userRegisterStatisticsVo.getOtherCount()-userRegisterStatisticsVo.getOtherPreMonthCount())/
                (userRegisterStatisticsVo.getOtherPreMonthCount()==0?1f:userRegisterStatisticsVo.getOtherPreMonthCount()))));
        //其他同比
        userRegisterStatisticsVo.setOtherYearOnYear(Float.parseFloat(numberFormat.format( (userRegisterStatisticsVo.getOtherCount()-userRegisterStatisticsVo.getOtherPreYearCount())/
                (userRegisterStatisticsVo.getOtherPreYearCount()==0?1f:userRegisterStatisticsVo.getOtherPreYearCount()))));
        //日增长率
        userRegisterStatisticsVo.setRateOfRise(Float.parseFloat(numberFormat.format( (userRegisterStatisticsVo.getCount()-userRegisterStatisticsVo.getPreDayCount())/
                (userRegisterStatisticsVo.getPreDayCount()==0?1f:userRegisterStatisticsVo.getPreDayCount()))));

        redisClusterServer.setex(String.format("%s%s",RedisKeys.USER_REGISTER_STATISTIC_INFO,format.format(new Date())),JsonUtils.toJsonString(userRegisterStatisticsVo), RedisConstants.ONE_DAY);
        return userRegisterStatisticsVo;
    }

    @Override
    public UserRegisterStatisticsVo getDayRegisterStatistics() {
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        String now = format.format(new Date());
        UserRegisterStatisticsVo userRegisterStatisticsVo = new UserRegisterStatisticsVo();
        String registerInfo = redisClusterServer.get(String.format("%s%s",RedisKeys.USER_REGISTER_DAY_STATISTIC, now));
        if(StringUtils.isNotBlank(registerInfo)){
            return JsonUtils.readValue(registerInfo, UserRegisterStatisticsVo.class);
        }
        List<UserRegisterInfo> userRegisterInfoList = userWebDao.getWeekRegisterCount();
        if(userRegisterInfoList == null || userRegisterInfoList.isEmpty()){
            return userRegisterStatisticsVo;
        }

        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.DATE,-1);
        String yesterday = format.format(calendar.getTime());
        calendar.add(Calendar.MONTH,-1);
        String beforeYesterday = format.format(calendar.getTime());

        userRegisterStatisticsVo.setRegisterTime(yesterday);
        for(UserRegisterInfo userRegisterInfo : userRegisterInfoList) {
            setClientStatistics(userRegisterStatisticsVo,userRegisterInfo,yesterday,beforeYesterday,"","");
        }
        DecimalFormat numberFormat = new DecimalFormat("##.##");
        //日增长率
        userRegisterStatisticsVo.setRateOfRise(Float.parseFloat(numberFormat.format( (userRegisterStatisticsVo.getCount()-userRegisterStatisticsVo.getPreDayCount())/
                (userRegisterStatisticsVo.getPreDayCount()==0?1f:userRegisterStatisticsVo.getPreDayCount()))));

        redisClusterServer.setex(String.format("%s%s",RedisKeys.USER_REGISTER_DAY_STATISTIC,format.format(new Date())),JsonUtils.toJsonString(userRegisterStatisticsVo), RedisConstants.ONE_DAY);
        return userRegisterStatisticsVo;
    }

    /**
     * @Title: 设置注册统计信息（昨天，前天，上个月昨天，去年昨天）
     * @Description:
     * @param
     * @return
     * @throw
     * @author lixiangling
     * @date 2018/8/30 17:49
     *  --------------------------------------------------------
     *  modifyer    modifyTime                 comment
     *
     *  --------------------------------------------------------
     */
    private void setClientStatistics(UserRegisterStatisticsVo userRegisterStatisticsVo,UserRegisterInfo userRegisterInfo,
                     String yesterday,String beforeYesterDay,String lastMonthYesterDay,String lastYearYesterDay ){
        String clientType = getClientType(userRegisterInfo.getClient());
        if(yesterday.equals(userRegisterInfo.getRegisterTime())){
            userRegisterStatisticsVo.setCount(userRegisterStatisticsVo.getCount()+userRegisterInfo.getCount());
            if(clientType.equals(CLIENT_TYPE_OTHER)){
                userRegisterStatisticsVo.setOtherCount(userRegisterStatisticsVo.getOtherCount()+userRegisterInfo.getCount());
            }else if(clientType.equals(PlatformEnumType.ANDROID.getKey())){
                userRegisterStatisticsVo.setAndroidCount(userRegisterStatisticsVo.getAndroidCount()+userRegisterInfo.getCount());
            }else if(clientType.equals(PlatformEnumType.IOS.getKey())){
                userRegisterStatisticsVo.setIosCount(userRegisterStatisticsVo.getIosCount()+userRegisterInfo.getCount());
            }else if(clientType.equals(PlatformEnumType.PC.getKey())){
                userRegisterStatisticsVo.setIosCount(userRegisterStatisticsVo.getPcCount()+userRegisterInfo.getCount());
            }
        }else if(beforeYesterDay.equals(userRegisterInfo.getRegisterTime())){
            userRegisterStatisticsVo.setPreDayCount(userRegisterStatisticsVo.getPreDayCount()+userRegisterInfo.getCount());
        }else if(yesterday.equals(userRegisterInfo.getRegisterTime())){
            userRegisterStatisticsVo.setCount(userRegisterStatisticsVo.getCount()+userRegisterInfo.getCount());
            if(clientType.equals(CLIENT_TYPE_OTHER)){
                userRegisterStatisticsVo.setOtherCount(userRegisterStatisticsVo.getOtherCount()+userRegisterInfo.getCount());
            }else if(clientType.equals(PlatformEnumType.ANDROID.getKey())){
                userRegisterStatisticsVo.setAndroidCount(userRegisterStatisticsVo.getAndroidCount()+userRegisterInfo.getCount());
            }else if(clientType.equals(PlatformEnumType.IOS.getKey())){
                userRegisterStatisticsVo.setIosCount(userRegisterStatisticsVo.getIosCount()+userRegisterInfo.getCount());
            }else if(clientType.equals(PlatformEnumType.PC.getKey())){
                userRegisterStatisticsVo.setIosCount(userRegisterStatisticsVo.getPcCount()+userRegisterInfo.getCount());
            }
        }else if(lastMonthYesterDay.equals(userRegisterInfo.getRegisterTime())){
            if(clientType.equals(CLIENT_TYPE_OTHER)){
                userRegisterStatisticsVo.setOtherPreMonthCount(userRegisterStatisticsVo.getOtherPreMonthCount()+userRegisterInfo.getCount());
            }else if(clientType.equals(PlatformEnumType.ANDROID.getKey())){
                userRegisterStatisticsVo.setAndroidPreMonthCount(userRegisterStatisticsVo.getAndroidPreMonthCount()+userRegisterInfo.getCount());
            }else if(clientType.equals(PlatformEnumType.IOS.getKey())){
                userRegisterStatisticsVo.setIosPreMonthCount(userRegisterStatisticsVo.getIosPreMonthCount()+userRegisterInfo.getCount());
            }else if(clientType.equals(PlatformEnumType.PC.getKey())){
                userRegisterStatisticsVo.setPcPreMonthCount(userRegisterStatisticsVo.getPcPreMonthCount()+userRegisterInfo.getCount());
            }
        }else if(lastYearYesterDay.equals(userRegisterInfo.getRegisterTime())){
            if(clientType.equals(CLIENT_TYPE_OTHER)){
                userRegisterStatisticsVo.setOtherPreYearCount(userRegisterStatisticsVo.getOtherPreYearCount()+userRegisterInfo.getCount());
            }else if(clientType.equals(PlatformEnumType.ANDROID.getKey())){
                userRegisterStatisticsVo.setAndroidPreYearCount(userRegisterStatisticsVo.getAndroidPreYearCount()+userRegisterInfo.getCount());
            }else if(clientType.equals(PlatformEnumType.IOS.getKey())){
                userRegisterStatisticsVo.setIosPreYearCount(userRegisterStatisticsVo.getIosPreYearCount()+userRegisterInfo.getCount());
            }else if(clientType.equals(PlatformEnumType.PC.getKey())){
                userRegisterStatisticsVo.setPcPreYearCount(userRegisterStatisticsVo.getPcPreYearCount()+userRegisterInfo.getCount());
            }
        }
    }
    /**
     * @Title: 获取正确的客户端类型
     * @Description:
     * @param
     * @return
     * @throw
     * @author lixiangling
     * @date 2018/8/30 17:49
     *  --------------------------------------------------------
     *  modifyer    modifyTime                 comment
     *
     *  --------------------------------------------------------
     */
    private String getClientType(String client){
        if(StringUtils.isBlank(client)){
            return CLIENT_TYPE_OTHER;
        }else if(client.startsWith(PlatformEnumType.ANDROID.getKey())){
            return PlatformEnumType.ANDROID.getKey();
        }else if(client.startsWith(PlatformEnumType.IOS.getKey())){
            return PlatformEnumType.IOS.getKey();
        }else if(client.startsWith(PlatformEnumType.PC.getKey())||client.startsWith("pc")){
            return PlatformEnumType.PC.getKey();
        }else{
            return CLIENT_TYPE_OTHER;
        }
    }
}